package com.tbit.main.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.tbit.main.constant.RedisConstant;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.ListUtil;
import com.tbit.main.util.LogUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author LMY
 * @create 2023-03-15 16:27
 */
@Service
public class GreatopsServiceImpl implements GreatopsService {

    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private MachineStatusService machineStatusService;
    @Autowired
    private MachineAbnormalService machineAbnormalService;
    @Autowired
    private MachineFaultService machineFaultService;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private BatteryModelService batteryModelService;
    @Autowired
    private MachineOccupyService machineOccupyService;
    @Autowired
    private BatteryMachineService batteryMachineService;
    @Autowired
    private AccountUserService accountUserService;
    @Autowired
    private DataService dataService;
    @Autowired
    private StockMachineService stockMachineService;

    @Override
    public GreatopsMachine getMachineStatus(Greatops greatops, List<Integer> regionId) {
        GreatopsMachine machineGreatops = new GreatopsMachine();
        long t2 = System.currentTimeMillis();

        /**查询参数*/
        Integer accountId = greatops.getAccountId();
        Integer mapType = greatops.getMapType();
        List<Integer> faultState = greatops.getFaultState();
        List<Integer> abnormalType = greatops.getAbnormalType();

        /**获取电池编号*/
        List<BatteryMachine> batteryMachineList;
        if (CollUtil.isEmpty(regionId)) {
            batteryMachineList = batteryMachineService.getByAccountId(accountId);
        } else {
            batteryMachineList = batteryMachineService.getByRegionIds(regionId);
        }
        Map<Integer, String> batteryMachineMap = batteryMachineList.parallelStream().collect(Collectors.toMap(BatteryMachine::getMachineId, BatteryMachine::getBatterNO));

        /**查询电池方案*/
        List<MachineBatteryModel> machineBatterys = batteryModelService.getMachineBatteryModel(accountId);
        Map<Integer, Integer> machineBatteryMap = machineBatterys.parallelStream().collect(Collectors.toMap(MachineBatteryModel::getMachineId, MachineBatteryModel::getBatteryModelId));

        /**获取车辆信息*/
        List<Machine> machines = machineService.getByAccountId(accountId);
        Map<Integer, Machine> machineMap = machines.parallelStream().collect(Collectors.toMap(Machine::getMachineId, machine -> machine));

        /**查询缺电车辆*/
        if (greatops.getPowerSwitch().equals(1)) {

            List<MachineStatus> machinePowerStatus;
            if (CollUtil.isEmpty(regionId)) {
                machinePowerStatus = machineStatusService.getSocByKey(accountId, greatops.getStartSoc(), greatops.getEndSoc());
            } else {
                machinePowerStatus = machineStatusService.getSocByRegionIdAndKey(regionId, greatops.getStartSoc(), greatops.getEndSoc());
            }

            /** 校准 */
            if (CollUtil.isNotEmpty(machinePowerStatus)) {
                List<StockMachine> stockMachines = stockMachineService.getByAccountId(accountId, regionId);
                List<Integer> machineIds = stockMachines.stream().map(StockMachine::getMachineId).collect(Collectors.toList());

                Map<Boolean, List<MachineStatus>> map = machinePowerStatus.stream().collect(Collectors.partitioningBy(s ->
                        !machineIds.contains(s.getMachineId())));
                machinePowerStatus = map.get(true);

                /**校准*/
                calibrateService.celibrateMachineStatus(machinePowerStatus, mapType);

                /** 查询当前在使用车辆 */
                List<MachineBorrow> machineBorrows;
                if (CollUtil.isEmpty(regionId)) {
                    machineBorrows = machineBorrowService.getByAccountId(accountId);
                } else {
                    machineBorrows = machineBorrowService.getByRegionId(regionId);
                }
                Map<Integer, MachineBorrow> machineBorrowMap = machineBorrows.parallelStream().collect(Collectors.toMap(MachineBorrow::getMachineId, machineBorrow -> machineBorrow));

                for (MachineStatus ms : machinePowerStatus) {
                    if (machineBorrowMap.containsKey(ms.getMachineId())) {
                        ms.setInUse(1);
                    } else {
                        ms.setInUse(0);
                    }
                    Integer batteryModelId = machineBatteryMap.get(ms.getMachineId());
                    ms.setBatteryModelId(batteryModelId);
                    ms.setBatteryNO(batteryMachineMap.get(ms.getMachineId()));
                }
            }
            /** 保存电量小于20的车辆*/
            List<Integer> machineIdList = machinePowerStatus.parallelStream().filter(machineStatus1 -> machineStatus1.getSocPercent() <= 20).map(MachineStatus::getMachineId).collect(Collectors.toList());
            machineGreatops.setMachineId(machineIdList);
            machineGreatops.setListMachineStatus(machinePowerStatus);
        }
        if (greatops.getFaultSwitch().equals(1)) {
            /** 查询故障车辆*/
            List<MachineStatusFault> machineStatusFaults = new ArrayList<MachineStatusFault>();
            /**查询所有设备状态*/
            List<MachineStatus> machineStatuses;
            if (CollUtil.isEmpty(regionId)) {
                machineStatuses = machineStatusService.getFaultByAccountId(accountId, faultState);
            } else {
                machineStatuses = machineStatusService.getFaultByRegionId(regionId, faultState);
            }

            if (CollUtil.isNotEmpty(machineStatuses)) {
                /**校准*/
                calibrateService.celibrateMachineStatus(machineStatuses, mapType);

                /**查询故障*/
                List<MachineFault> machineFaults;
                if (CollUtil.isEmpty(regionId)) {
                    machineFaults = machineFaultService.getByAccountId(accountId);
                } else {
                    machineFaults = machineFaultService.getByRegionId(regionId);
                }
                Map<Integer, MachineFault> machineFaultMap = machineFaults.parallelStream().collect(Collectors.toMap(MachineFault::getMachineId, machineFault -> machineFault));

                for (MachineStatus ms : machineStatuses) {
                    MachineStatusFault msf = new MachineStatusFault();
                    msf.setMachineId(ms.getMachineId());
                    msf.setMachineNO(ms.getMachineNO());
                    msf.setLon(ms.getLon());
                    msf.setLat(ms.getLat());
                    msf.setLonC(ms.getLonC());
                    msf.setLatC(ms.getLatC());
                    msf.setPosDt(ms.getPosDt());
                    msf.setBatDt(ms.getBatDt());
                    msf.setSocPercent(ms.getSocPercent());
                    msf.setSurplusMileage(ms.getSurplusMileage());
                    msf.setState(ms.getState());
                    msf.setBatteryNO(batteryMachineMap.get(ms.getMachineId()));
                    /**故障来源*/
                    MachineFault mf = machineFaultMap.get(msf.getMachineId());
                    if (mf != null) {
                        msf.setFaultFrom(mf.getFrom());
                        /**故障类型*/
                        msf.setFaultType(mf.getFaults());
                        machineStatusFaults.add(msf);
                    }
                }
            }

            /**查询设备编号和用户码*/
            if (CollUtil.isNotEmpty(machineStatusFaults)) {
                for (MachineStatusFault ms : machineStatusFaults) {
                    Machine machine = machineMap.get(ms.getMachineId());
                    if (machine != null) {
                        ms.setMachineNO(machine.getMachineNO());
                        ms.setUserCode(machine.getUserCode());
                        ms.setMachineType(machine.getMachineType());
                    }
                }
            }

            for (MachineStatusFault ms : machineStatusFaults) {
                Integer batteryModelId = machineBatteryMap.get(ms.getMachineId());
                ms.setBatteryModelId(batteryModelId);
            }

            // 获取故障车辆id
            if (CollUtil.isNotEmpty(machineStatusFaults)) {
                List<Integer> machineIdList = machineStatusFaults.parallelStream().map(MachineStatusFault::getMachineId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(machineGreatops.getMachineId())) {
                    // 获取存在故障不同machineId
                    List<Integer> different = ListUtil.getDifferentIntegerList(machineGreatops.getMachineId(), machineIdList);
                    // 添加到总list中
                    machineGreatops.getMachineId().addAll(different);
                    // 获取相同machineId
                    List<Integer> steam = ListUtil.getSameIntegerList(machineIdList, different);
                    // 去除存在故障中相同machineId
                    machineStatusFaults = machineStatusFaults.parallelStream().filter(s -> !steam.contains(s.getMachineId())).collect(Collectors.toList());
                }
                machineGreatops.setListMachineStatusFault(machineStatusFaults);
            }
        }
        if (greatops.getAbnormalSwitch().equals(1)) {
            /** 查询异常车辆*/
            List<MachineStatusAbnormal> machineStatusAbnormales = new ArrayList<MachineStatusAbnormal>();
            /**查询异常车辆*/
            List<MachineAbnormal> machineAbnormals;
            if (CollUtil.isEmpty(regionId)) {
                machineAbnormals = machineAbnormalService.groupByMachineIdAndListType(accountId, abnormalType);
            } else {
                machineAbnormals = machineAbnormalService.groupByMachineIdRegionIdAndType2(regionId, abnormalType);
            }
            if (CollUtil.isNotEmpty(machineAbnormals)) {
                List<Integer> machineIds = machineAbnormals.parallelStream().map(MachineAbnormal::getAccountId).collect(Collectors.toList());
                Map<Integer, Integer> abnormalMap = machineAbnormals.parallelStream().collect(Collectors.toMap(MachineAbnormal::getMachineId, MachineAbnormal::getAbnormalType));

                /**查询所有设备状态*/
                List<MachineStatus> machineStatuses = machineStatusService.getByMachineIdBatch(machineIds);

                if (CollUtil.isNotEmpty(machineStatuses)) {
                    /**校准*/
                    calibrateService.celibrateMachineStatus(machineStatuses, mapType);

                    for (MachineStatus ms : machineStatuses) {
                        MachineStatusAbnormal msa = new MachineStatusAbnormal();

                        msa.setMachineId(ms.getMachineId());
                        msa.setMachineNO(ms.getMachineNO());
                        msa.setLon(ms.getLon());
                        msa.setLat(ms.getLat());
                        msa.setLonC(ms.getLonC());
                        msa.setLatC(ms.getLatC());
                        msa.setPosDt(ms.getPosDt());
                        msa.setBatDt(ms.getBatDt());
                        msa.setSocPercent(ms.getSocPercent());
                        msa.setSurplusMileage(ms.getSurplusMileage());
                        msa.setBatteryNO(batteryMachineMap.get(ms.getMachineId()));
                        msa.setState(ms.getState());
                        /**异常类型*/
                        Integer abnormalTypeCache = abnormalMap.get(ms.getMachineId());
                        if (abnormalTypeCache != null) {
                            msa.setAbnormalType(abnormalTypeCache);
                        }
                        machineStatusAbnormales.add(msa);
                    }
                }
            }

            if (CollUtil.isNotEmpty(machineStatusAbnormales)) {
                /**查询设备编号和用户码*/
                if (CollUtil.isNotEmpty(machineStatusAbnormales)) {
                    for (MachineStatusAbnormal ms : machineStatusAbnormales) {
                        Machine machine = machineMap.get(ms.getMachineId());
                        if (machine != null) {
                            ms.setMachineNO(machine.getMachineNO());
                            ms.setUserCode(machine.getUserCode());
                        }
                    }
                }
            }
            for (MachineStatusAbnormal ms : machineStatusAbnormales) {
                Integer batteryModelId = machineBatteryMap.get(ms.getMachineId());
                ms.setBatteryModelId(batteryModelId);
            }

            // 获取异常车辆id
            if (CollUtil.isNotEmpty(machineStatusAbnormales)) {
                List<Integer> machineIdList = machineStatusAbnormales.parallelStream().map(MachineStatusAbnormal::getMachineId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(machineGreatops.getMachineId())) {
                    // 获取存在异常不同machineId
                    List<Integer> different = ListUtil.getDifferentIntegerList(machineGreatops.getMachineId(), machineIdList);
                    // 添加到总list中
                    machineGreatops.getMachineId().addAll(different);
                    // 获取相同machineId
                    List<Integer> steam = ListUtil.getSameIntegerList(machineIdList, different);
                    // 去除存在异常中相同machineId
                    machineStatusAbnormales = machineStatusAbnormales.parallelStream().filter(s -> !steam.contains(s.getMachineId())).collect(Collectors.toList());
                }
                machineGreatops.setListMachineStatusAbnormal(machineStatusAbnormales);
            }
        }
        if (greatops.getIdleTimeSwitch().equals(1)) {
            /** 查询闲置车辆*/
            List<MachineStatusBorrow> machineStatusBorrows;

            if (CollUtil.isEmpty(regionId)) {
                machineStatusBorrows = machineStatusService.getAccountIdleTimeByStartEnd(accountId, greatops.getStartIdleTime(), greatops.getEndIdleTime());
            } else {
                machineStatusBorrows = machineStatusService.getRegionIdleTimeByStartEnd(regionId, greatops.getStartIdleTime(), greatops.getEndIdleTime());
            }

            /**校准*/
            if (CollUtil.isNotEmpty(machineStatusBorrows)) {
                calibrateService.celibrateMachineStatusBorrow(machineStatusBorrows, mapType);

                /**挪车调度，区域*/
                List<String> userCodeMove = new LinkedList<>();
                try {
                    userCodeMove = redisService.getList(RedisConstant.REDIS_BATCH_MOVE_AREA + accountId);
                } catch (SerializationException e) {
                    redisService.del(RedisConstant.REDIS_BATCH_MOVE_AREA + accountId);
                }

                List<String> machineNOMov = new ArrayList<>();
                if (CollUtil.isNotEmpty(userCodeMove)) {
                    for (String userCode : userCodeMove) {
                        machineNOMov.add(dataService.getMachineNO(userCode));
                    }
                }

                /**批量调度，区域*/
                List<String> areaDispatchMachineCache = new LinkedList<>();
                try {
                    areaDispatchMachineCache = redisService.getList(RedisConstant.REDIS_BATCH_DISPATCH_AREA + accountId);
                } catch (SerializationException e) {
                    redisService.del(RedisConstant.REDIS_BATCH_DISPATCH_AREA + accountId);
                }

                List<String> machineNODis = new ArrayList<>();
                if (CollUtil.isNotEmpty(areaDispatchMachineCache)) {
                    for (String userCode : areaDispatchMachineCache) {
                        machineNODis.add(dataService.getMachineNO(userCode));
                    }
                }

                for (MachineStatusBorrow msb : machineStatusBorrows) {
                    /**挪车*/
                    if (machineNOMov.contains(msb.getMachineNO())) {
                        msb.setMoveState(1);
                        continue;
                    }

                    /**调度*/
                    if (machineNODis.contains(msb.getMachineNO())) {
                        msb.setMoveState(2);
                    }
                }
            }

            for (MachineStatusBorrow ms : machineStatusBorrows) {
                Integer batteryModelId = machineBatteryMap.get(ms.getMachineId());
                ms.setBatteryModelId(batteryModelId);
                ms.setBatteryNO(batteryMachineMap.get(ms.getMachineId()));
            }

            // 获取闲置车辆id
            if (CollUtil.isNotEmpty(machineStatusBorrows)) {
                List<Integer> machineIdList = machineStatusBorrows.parallelStream().map(MachineStatusBorrow::getMachineId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(machineGreatops.getMachineId())) {
                    // 获取存在闲置不同machineId
                    List<Integer> different = ListUtil.getDifferentIntegerList(machineGreatops.getMachineId(), machineIdList);
                    // 添加到总list中
                    machineGreatops.getMachineId().addAll(different);
                    // 获取相同machineId
                    List<Integer> steam = ListUtil.getSameIntegerList(machineIdList, different);
                    // 去除存在异常中相同machineId
                    machineStatusBorrows = machineStatusBorrows.parallelStream().filter(s -> !steam.contains(s.getMachineId())).collect(Collectors.toList());
                }
                machineGreatops.setListMachineStatusBorrow(machineStatusBorrows);
            }
        }
        if (greatops.getOccupySwitch().equals(1) && greatops.getOccupyState().equals(0)) {
            /** 查询占用车辆*/
            List<MachineStatus> machineStatuses = new ArrayList<MachineStatus>();
            /**查询运维占用中车辆*/
            List<MachineOccupy> machineOccupys;
            if (CollUtil.isEmpty(regionId)) {
                machineOccupys = machineOccupyService.getByAccountId(accountId);
            } else {
                machineOccupys = machineOccupyService.getByRegionId(regionId);
            }
            if (CollUtil.isNotEmpty(machineOccupys)) {

                Map<Integer, Integer> occupyId = machineOccupys.parallelStream().collect(Collectors.toMap(MachineOccupy::getMachineId, MachineOccupy::getAccountUserId));
                List<Integer> machineIds = machineOccupys.parallelStream().map(MachineOccupy::getMachineId).collect(Collectors.toList());

                machineStatuses = machineStatusService.getByMachineIdBatch(machineIds);

                /**运维人员*/
                List<AccountUser> accountUsers = accountUserService.getByIds(new ArrayList<>(occupyId.values()));
                Map<Integer, String> accountUserMap = accountUsers.parallelStream().collect(Collectors.toMap(AccountUser::getAccountUserId, AccountUser::getName));

                for (MachineStatus ms : machineStatuses) {
                    Machine machine = machineMap.get(ms.getMachineId());
                    if (machine != null) {
                        ms.setMachineNO(machine.getMachineNO());
                        ms.setUserCode(machine.getUserCode());
                        ms.setBatteryNO(batteryMachineMap.get(ms.getMachineId()));
                    }
                    ms.setUserId(occupyId.get(ms.getMachineId()));
                    ms.setUserName(accountUserMap.get(occupyId.get(ms.getMachineId())));
                }

                /** 校准 */
                if (CollUtil.isNotEmpty(machineStatuses)) {
                    /**校准*/
                    calibrateService.celibrateMachineStatus(machineStatuses, mapType);
                }
            }

            for (MachineStatus ms : machineStatuses) {
                Integer batteryModelId = machineBatteryMap.get(ms.getMachineId());
                ms.setBatteryModelId(batteryModelId);
            }

            // 获取占用车辆id
            if (CollUtil.isNotEmpty(machineStatuses)) {
                List<Integer> machineIdList = machineStatuses.parallelStream().map(MachineStatus::getMachineId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(machineGreatops.getMachineId())) {
                    // 获取存在占用不同machineId
                    List<Integer> different = ListUtil.getDifferentIntegerList(machineGreatops.getMachineId(), machineIdList);
                    // 添加到总list中
                    machineGreatops.getMachineId().addAll(different);
                    // 获取相同machineId
                    List<Integer> steam = ListUtil.getSameIntegerList(machineIdList, different);
                    // 去除存在占用中相同machineId
                    machineStatuses = machineStatuses.parallelStream().filter(s -> !steam.contains(s.getMachineId())).collect(Collectors.toList());
                }
                machineGreatops.setListMachineStatus(machineStatuses);
            }
        }
        if (greatops.getPowerSwitch().equals(1)) {
            /**排除换电中 (故障，异常，闲置，占用)且电量大于20的车辆*/
            List<MachineStatus> machineStatuses = machineGreatops.getListMachineStatus();
            // 电量大于20machineId
            List<Integer> power = new LinkedList<>();
            for (MachineStatus machineStatus : machineStatuses) {
                if (machineStatus.getSocPercent() > 20) {
                    power.add(machineStatus.getMachineId());
                }
            }

            // 获取存在闲置不同machineId
            List<Integer> different = ListUtil.getDifferentIntegerList(machineGreatops.getMachineId(), power);
            // 获取相同machineId
            List<Integer> steam = ListUtil.getSameIntegerList(power, different);
            for (Integer machineId : steam) {
                machineStatuses = machineStatuses.parallelStream().filter(s -> !s.getMachineId().equals(machineId)).collect(Collectors.toList());
            }
            machineGreatops.setListMachineStatus(machineStatuses);
        }
        long t1 = System.currentTimeMillis();
        LogUtil.info(String.format("[GreatopsServiceImpl][getMachineStatus][执行耗时：%sms]", (t1 - t2)));
        return machineGreatops;
    }
}
